import sys
import os
import json
import time
import shutil
from datetime import datetime, timedelta
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
    QListWidget, QListWidgetItem, QLabel, QTabWidget, QMessageBox, QMenu,
    QDialog, QTextEdit, QLineEdit, QDateEdit, QComboBox, QTableWidget, QTableWidgetItem,
    QSystemTrayIcon, QStyle, QFileDialog
)
from PySide6.QtCore import Qt, QTimer, QPoint, QDate, QSize
from PySide6.QtGui import QIcon, QPixmap, QClipboard, QAction
import win32clipboard
from PIL import ImageGrab, Image
import base64
import hashlib
import subprocess

class AboutDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("关于")
        self.setFixedSize(400, 500)
        
        layout = QVBoxLayout()
        
        # 标题
        title_label = QLabel("剪贴板管理器")
        title_label.setStyleSheet("font-size: 24px; font-weight: bold;")
        title_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(title_label)
        
        # 版本信息
        version_label = QLabel("版本: 1.0.0")
        version_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(version_label)
        
        # 作者信息
        author_label = QLabel("作者: Hamt")
        author_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(author_label)
        
        # 联系方式
        contact_label = QLabel("微信号: hangfeiwangluo")
        contact_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(contact_label)
        
        # 二维码图片
        qrcode_path = self.parent()._get_resource_path("qrcode.png")
        if os.path.exists(qrcode_path):
            qrcode_label = QLabel()
            pixmap = QPixmap(qrcode_path)
            scaled_pixmap = pixmap.scaled(200, 200, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            qrcode_label.setPixmap(scaled_pixmap)
            qrcode_label.setAlignment(Qt.AlignCenter)
            layout.addWidget(qrcode_label)
        
        # 提示信息
        tip_label = QLabel("如有任何问题或建议，欢迎通过微信联系我！")
        tip_label.setAlignment(Qt.AlignCenter)
        tip_label.setWordWrap(True)
        layout.addWidget(tip_label)
        
        # 确定按钮
        ok_button = QPushButton("确定")
        ok_button.clicked.connect(self.accept)
        layout.addWidget(ok_button)
        
        self.setLayout(layout)

class SettingsDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("设置")
        self.setFixedSize(500, 200)
        
        layout = QVBoxLayout()
        
        # 文件大小限制设置
        size_layout = QHBoxLayout()
        size_label = QLabel("文件复制大小限制(MB):")
        self.size_edit = QLineEdit()
        self.size_edit.setText(str(parent.max_file_size // (1024 * 1024)))
        size_layout.addWidget(size_label)
        size_layout.addWidget(self.size_edit)
        layout.addLayout(size_layout)
        
        # 按钮
        button_layout = QHBoxLayout()
        save_button = QPushButton("保存")
        save_button.clicked.connect(self.save_settings)
        cancel_button = QPushButton("取消")
        cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(save_button)
        button_layout.addWidget(cancel_button)
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def save_settings(self):
        try:
            new_size = int(self.size_edit.text().strip())
            if new_size <= 0:
                raise ValueError("文件大小限制必须大于0")
        except ValueError as e:
            QMessageBox.warning(self, "警告", f"文件大小限制无效: {str(e)}")
            return
        
        # 保存设置到配置文件
        settings = {
            "max_file_size": new_size * 1024 * 1024  # 转换为字节
        }
        settings_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "settings.json")
        
        # 如果配置文件存在，先读取现有设置
        if os.path.exists(settings_file):
            try:
                with open(settings_file, 'r', encoding='utf-8') as f:
                    existing_settings = json.load(f)
                    settings.update(existing_settings)
            except Exception as e:
                print(f"读取现有设置失败: {str(e)}")
        
        # 保存更新后的设置
        try:
            with open(settings_file, 'w', encoding='utf-8') as f:
                json.dump(settings, f, ensure_ascii=False, indent=2)
            
            # 更新父窗口的设置
            self.parent().max_file_size = new_size * 1024 * 1024
            
            QMessageBox.information(self, "提示", "设置已保存")
            self.accept()
        except Exception as e:
            QMessageBox.warning(self, "警告", f"保存设置失败: {str(e)}")

class ClipboardManager(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("剪贴板管理器")
        self.setGeometry(100, 100, 800, 600)
        # 设置窗口标志，使其最小化时不显示在任务栏
        self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        
        # 设置窗口图标
        icon_path = self._get_resource_path("clipboard.ico")
        if os.path.exists(icon_path):
            self.setWindowIcon(QIcon(icon_path))
        else:
            # 使用系统默认图标
            self.setWindowIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_ComputerIcon))
        
        # 创建菜单栏
        self._create_menu_bar()
        
        # 加载设置
        self._load_settings()
        
        # 创建数据存储目录
        self._create_directories()
        self.history = self._load_history()
        
        # 创建系统托盘图标
        self._create_tray_icon()
        
        # 创建主界面
        self._create_ui()
        
        # 设置定时器检查剪贴板
        self.timer = QTimer()
        self.timer.timeout.connect(self.check_clipboard)
        self.timer.start(1000)  # 每秒检查一次
        
        self.last_clipboard_content = None
        self.last_clipboard_hash = None
        self.last_image_hash = None
        self.last_file_list_hash = None

    def _get_resource_path(self, relative_path):
        """获取资源文件的绝对路径"""
        if getattr(sys, 'frozen', False):
            # 如果是打包后的exe
            base_path = sys._MEIPASS
        else:
            # 如果是开发环境
            base_path = os.path.dirname(os.path.abspath(__file__))
        return os.path.join(base_path, relative_path)

    def _load_settings(self):
        """加载设置"""
        # 获取程序根目录（exe所在目录）
        if getattr(sys, 'frozen', False):
            # 如果是打包后的exe
            root_dir = os.path.dirname(sys.executable)
        else:
            # 如果是开发环境
            root_dir = os.path.dirname(os.path.abspath(__file__))
            
        self.data_dir = os.path.join(root_dir, "data")
        self.images_dir = os.path.join(self.data_dir, "images")
        self.files_dir = os.path.join(self.data_dir, "files")
        self.history_file = os.path.join(self.data_dir, "history.json")
        
        # 默认文件大小限制为100MB
        self.max_file_size = 100 * 1024 * 1024
        
        # 尝试加载设置文件
        settings_file = os.path.join(root_dir, "settings.json")
        if os.path.exists(settings_file):
            try:
                with open(settings_file, 'r', encoding='utf-8') as f:
                    settings = json.load(f)
                    if "max_file_size" in settings:
                        self.max_file_size = settings["max_file_size"]
            except Exception as e:
                print(f"加载设置失败: {str(e)}")

    def _create_directories(self):
        """创建必要的目录"""
        try:
            os.makedirs(self.data_dir, exist_ok=True)
            os.makedirs(self.images_dir, exist_ok=True)
            os.makedirs(self.files_dir, exist_ok=True)
        except Exception as e:
            QMessageBox.critical(self, "错误", f"创建目录失败: {str(e)}")

    def _load_history(self):
        """加载历史记录"""
        if os.path.exists(self.history_file):
            try:
                with open(self.history_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except Exception as e:
                QMessageBox.warning(self, "警告", f"加载历史记录失败: {str(e)}")
                return {"text": [], "images": [], "files": []}
        return {"text": [], "images": [], "files": []}

    def _save_history(self):
        """保存历史记录"""
        try:
            with open(self.history_file, 'w', encoding='utf-8') as f:
                json.dump(self.history, f, ensure_ascii=False, indent=2)
        except Exception as e:
            QMessageBox.warning(self, "警告", f"保存历史记录失败: {str(e)}")

    def _create_tray_icon(self):
        """创建系统托盘图标"""
        self.tray_icon = QSystemTrayIcon(self)
        # 使用与窗口相同的图标
        self.tray_icon.setIcon(self.windowIcon())
        
        # 创建托盘菜单
        tray_menu = QMenu()
        show_action = QAction("显示", self)
        show_action.triggered.connect(self.show)
        tray_menu.addAction(show_action)
        
        hide_action = QAction("隐藏", self)
        hide_action.triggered.connect(self.hide)
        tray_menu.addAction(hide_action)
        
        # 添加关于菜单项
        about_action = QAction("关于", self)
        about_action.triggered.connect(self.show_about)
        tray_menu.addAction(about_action)
        
        quit_action = QAction("退出", self)
        quit_action.triggered.connect(self.close_application)
        tray_menu.addAction(quit_action)
        
        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()
        
        # 双击托盘图标显示窗口
        self.tray_icon.activated.connect(self.tray_icon_activated)

    def tray_icon_activated(self, reason):
        """处理托盘图标的激活事件"""
        if reason == QSystemTrayIcon.DoubleClick:
            if self.isVisible():
                self.hide()
            else:
                self.show()
                self.activateWindow()

    def changeEvent(self, event):
        """处理窗口状态改变事件"""
        if event.type() == event.WindowStateChange:
            if self.windowState() & Qt.WindowMinimized:
                # 窗口最小化时，直接隐藏窗口
                self.hide()
                # 重置窗口状态，避免任务栏显示
                self.setWindowState(Qt.WindowNoState)
        super().changeEvent(event)

    def closeEvent(self, event):
        """重写关闭事件，最小化到托盘"""
        event.ignore()  # 忽略关闭事件
        self.hide()     # 隐藏窗口
        self.setWindowState(Qt.WindowNoState)  # 重置窗口状态

    def _create_ui(self):
        """创建用户界面"""
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)

        tab_widget = QTabWidget()
        self.tab_widget = tab_widget

        # 文本标签页
        text_tab = QWidget()
        text_layout = QVBoxLayout(text_tab)
        text_search_layout = QHBoxLayout()
        self.text_search_edit = QLineEdit()
        self.text_search_edit.setPlaceholderText("搜索内容…")
        self.text_search_edit.textChanged.connect(self._update_ui)
        self.text_date_edit = QDateEdit()
        self.text_date_edit.setCalendarPopup(True)
        self.text_date_edit.setDisplayFormat("yyyy-MM-dd")
        self.text_date_edit.setDate(QDate.currentDate())
        self.text_date_edit.dateChanged.connect(self._update_ui)
        text_search_layout.addWidget(self.text_search_edit)
        text_search_layout.addWidget(self.text_date_edit)
        text_layout.addLayout(text_search_layout)
        # 用QTableWidget替换QListWidget
        self.text_table = QTableWidget()
        self.text_table.setColumnCount(2)
        self.text_table.setHorizontalHeaderLabels(["内容", "时间"])
        self.text_table.horizontalHeader().setStretchLastSection(True)
        self.text_table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.text_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.text_table.setSelectionMode(QTableWidget.SingleSelection)
        self.text_table.verticalHeader().setVisible(False)
        self.text_table.setShowGrid(False)
        text_layout.addWidget(self.text_table)
        tab_widget.addTab(text_tab, "文本")
        self.text_table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.text_table.customContextMenuRequested.connect(self.text_context_menu)
        self.text_table.itemDoubleClicked.connect(self.text_double_clicked)

        # 图片标签页
        image_tab = QWidget()
        image_layout = QVBoxLayout(image_tab)
        image_search_layout = QHBoxLayout()
        self.image_search_edit = QLineEdit()
        self.image_search_edit.setPlaceholderText("搜索文件名…")
        self.image_search_edit.textChanged.connect(self._update_ui)
        self.image_date_edit = QDateEdit()
        self.image_date_edit.setCalendarPopup(True)
        self.image_date_edit.setDisplayFormat("yyyy-MM-dd")
        self.image_date_edit.setDate(QDate.currentDate())
        self.image_date_edit.dateChanged.connect(self._update_ui)
        self.image_view_mode = QComboBox()
        self.image_view_mode.addItems(["文件名", "图片预览"])
        self.image_view_mode.currentIndexChanged.connect(self._update_ui)
        image_search_layout.addWidget(self.image_search_edit)
        image_search_layout.addWidget(self.image_date_edit)
        image_search_layout.addWidget(self.image_view_mode)
        image_layout.addLayout(image_search_layout)
        # 新增QTableWidget用于文件名模式
        self.image_table = QTableWidget()
        self.image_table.setColumnCount(2)
        self.image_table.setHorizontalHeaderLabels(["文件名", "时间"])
        self.image_table.horizontalHeader().setStretchLastSection(True)
        self.image_table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.image_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.image_table.setSelectionMode(QTableWidget.SingleSelection)
        self.image_table.verticalHeader().setVisible(False)
        self.image_table.setShowGrid(False)
        image_layout.addWidget(self.image_table)
        # 预览模式下仍用QListWidget
        self.image_list = QListWidget()
        self.image_list.setIconSize(QSize(180, 180))
        image_layout.addWidget(self.image_list)
        tab_widget.addTab(image_tab, "图片")
        self.image_table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.image_table.customContextMenuRequested.connect(self.image_context_menu)
        self.image_table.itemDoubleClicked.connect(self.image_double_clicked)
        self.image_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.image_list.customContextMenuRequested.connect(self.image_context_menu)
        self.image_list.itemDoubleClicked.connect(self.image_double_clicked)

        # 文件标签页
        file_tab = QWidget()
        file_layout = QVBoxLayout(file_tab)
        file_search_layout = QHBoxLayout()
        self.file_search_edit = QLineEdit()
        self.file_search_edit.setPlaceholderText("搜索文件名…")
        self.file_search_edit.textChanged.connect(self._update_ui)
        self.file_date_edit = QDateEdit()
        self.file_date_edit.setCalendarPopup(True)
        self.file_date_edit.setDisplayFormat("yyyy-MM-dd")
        self.file_date_edit.setDate(QDate.currentDate())
        self.file_date_edit.dateChanged.connect(self._update_ui)
        file_search_layout.addWidget(self.file_search_edit)
        file_search_layout.addWidget(self.file_date_edit)
        file_layout.addLayout(file_search_layout)
        # 新增QTableWidget用于文件分组
        self.file_table = QTableWidget()
        self.file_table.setColumnCount(2)
        self.file_table.setHorizontalHeaderLabels(["文件夹+文件名", "时间"])
        self.file_table.horizontalHeader().setStretchLastSection(True)
        self.file_table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.file_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.file_table.setSelectionMode(QTableWidget.SingleSelection)
        self.file_table.verticalHeader().setVisible(False)
        self.file_table.setShowGrid(False)
        file_layout.addWidget(self.file_table)
        self.file_table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.file_table.customContextMenuRequested.connect(self.file_context_menu)
        self.file_table.itemDoubleClicked.connect(self.file_double_clicked)
        tab_widget.addTab(file_tab, "文件")
        layout.addWidget(tab_widget)
        
        # 添加控制按钮
        button_layout = QHBoxLayout()
        clear_button = QPushButton("清除选中")
        clear_button.clicked.connect(self.clear_selected)
        button_layout.addWidget(clear_button)
        clear_tab_button = QPushButton("清空当前页")
        clear_tab_button.clicked.connect(self.clear_current_tab)
        button_layout.addWidget(clear_tab_button)
        clear_all_button = QPushButton("全部清空")
        clear_all_button.clicked.connect(self.clear_all_history)
        button_layout.addWidget(clear_all_button)
        clear_old_button = QPushButton("清空一个月前")
        clear_old_button.clicked.connect(self.clear_old_records)
        button_layout.addWidget(clear_old_button)
        button_layout.addStretch()
        layout.addLayout(button_layout)
        
        # 加载历史记录到界面
        self._update_ui()

    def _update_ui(self):
        """更新界面显示，文本分组用QTableWidget两列显示"""
        try:
            # 文本分组+搜索（QTableWidget实现）
            self.text_table.setRowCount(0)
            text_group = {}
            search_kw = self.text_search_edit.text().strip()
            date_str = self.text_date_edit.date().toString("yyyy-MM-dd")
            for item in self.history["text"]:
                date = item["timestamp"][:10]
                if date != date_str:
                    continue
                if search_kw and search_kw not in item["content"]:
                    continue
                text_group.setdefault(date, []).append(item)
            for date in sorted(text_group.keys(), reverse=True):
                # 分组标题（合并两列，加粗）
                row = self.text_table.rowCount()
                self.text_table.insertRow(row)
                group_item = QTableWidgetItem(f"【{date}】")
                group_item.setFlags(Qt.ItemIsEnabled)
                font = group_item.font()
                font.setBold(True)
                group_item.setFont(font)
                self.text_table.setItem(row, 0, group_item)
                self.text_table.setSpan(row, 0, 1, 2)
                for item in sorted(text_group[date], key=lambda x: x["timestamp"], reverse=True):
                    t = item["timestamp"][11:19]
                    content = item["content"].replace('\n', ' ')[:40]
                    row = self.text_table.rowCount()
                    self.text_table.insertRow(row)
                    content_item = QTableWidgetItem(content)
                    content_item.setData(Qt.UserRole, item)  # 绑定原始数据
                    time_item = QTableWidgetItem(t)
                    time_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                    self.text_table.setItem(row, 0, content_item)
                    self.text_table.setItem(row, 1, time_item)

            # 图片分组+搜索
            view_mode = self.image_view_mode.currentText()
            if view_mode == "图片预览":
                self.image_table.hide()
                self.image_list.show()
                self.image_list.clear()
                image_group = {}
                search_kw = self.image_search_edit.text().strip()
                date_str = self.image_date_edit.date().toString("yyyy-MM-dd")
                for item in self.history["images"]:
                    date = item["timestamp"][:10]
                    if date != date_str:
                        continue
                    if search_kw and search_kw not in os.path.basename(item["path"]):
                        continue
                    image_group.setdefault(date, []).append(item)
                for date in sorted(image_group.keys(), reverse=True):
                    for item in sorted(image_group[date], key=lambda x: datetime.fromisoformat(x["timestamp"]), reverse=True):
                        t = item["timestamp"][11:19]
                        if os.path.exists(item["path"]):
                            name = os.path.basename(item["path"])
                            from PIL import Image
                            pix = QPixmap(item["path"])
                            icon = QIcon(pix.scaled(100, 100, Qt.KeepAspectRatio, Qt.SmoothTransformation))
                            try:
                                with Image.open(item["path"]) as im:
                                    w, h = im.size
                                    res_str = f"{w}x{h}"
                            except Exception:
                                res_str = "?x?"
                            text = f"{name}\n{res_str}"
                            lwitem = QListWidgetItem(icon, text)
                            lwitem.setTextAlignment(Qt.AlignHCenter)
                            lwitem.setToolTip(f"{name}\n{res_str}\n{t}")
                            lwitem.setData(Qt.UserRole, item)
                            self.image_list.addItem(lwitem)
                self.image_list.setViewMode(QListWidget.IconMode)
                self.image_list.setResizeMode(QListWidget.Adjust)
                self.image_list.setGridSize(QSize(200, 220))
                self.image_list.setIconSize(QSize(180, 180))
                self.image_list.setSpacing(20)
                self.image_list.scrollToTop()
            else:
                self.image_list.hide()
                self.image_table.show()
                self.image_table.setRowCount(0)
                image_group = {}
                search_kw = self.image_search_edit.text().strip()
                date_str = self.image_date_edit.date().toString("yyyy-MM-dd")
                for item in self.history["images"]:
                    date = item["timestamp"][:10]
                    if date != date_str:
                        continue
                    if search_kw and search_kw not in os.path.basename(item["path"]):
                        continue
                    image_group.setdefault(date, []).append(item)
                for date in sorted(image_group.keys(), reverse=True):
                    row = self.image_table.rowCount()
                    self.image_table.insertRow(row)
                    group_item = QTableWidgetItem(f"【{date}】")
                    group_item.setFlags(Qt.ItemIsEnabled)
                    font = group_item.font()
                    font.setBold(True)
                    group_item.setFont(font)
                    self.image_table.setItem(row, 0, group_item)
                    self.image_table.setSpan(row, 0, 1, 2)
                    for item in sorted(image_group[date], key=lambda x: datetime.fromisoformat(x["timestamp"]), reverse=True):
                        t = item["timestamp"][11:19]
                        if os.path.exists(item["path"]):
                            name = os.path.basename(item["path"])
                            row = self.image_table.rowCount()
                            self.image_table.insertRow(row)
                            name_item = QTableWidgetItem(name)
                            time_item = QTableWidgetItem(t)
                            time_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                            self.image_table.setItem(row, 0, name_item)
                            self.image_table.setItem(row, 1, time_item)
                            name_item.setData(Qt.UserRole, item)
                            time_item.setData(Qt.UserRole, item)

            # 文件分组+搜索
            self.file_table.setRowCount(0)
            file_group = {}
            search_kw = self.file_search_edit.text().strip()
            date_str = self.file_date_edit.date().toString("yyyy-MM-dd")
            for item in self.history["files"]:
                date = item["timestamp"][:10]
                if date != date_str:
                    continue
                if search_kw and search_kw not in os.path.basename(item["path"]):
                    continue
                file_group.setdefault(date, []).append(item)
            for date in sorted(file_group.keys(), reverse=True):
                row = self.file_table.rowCount()
                self.file_table.insertRow(row)
                group_item = QTableWidgetItem(f"【{date}】")
                group_item.setFlags(Qt.ItemIsEnabled)
                font = group_item.font()
                font.setBold(True)
                group_item.setFont(font)
                self.file_table.setItem(row, 0, group_item)
                self.file_table.setSpan(row, 0, 1, 2)
                for item in sorted(file_group[date], key=lambda x: x["timestamp"], reverse=True):
                    t = item["timestamp"][11:19]
                    if os.path.exists(item["path"]):
                        name = os.path.basename(item["path"])
                        folder = os.path.dirname(item.get("original_path", item["path"]))
                        folder = folder.replace("\\", "/")  # 路径分隔符统一为/
                        row = self.file_table.rowCount()
                        self.file_table.insertRow(row)
                        name_item = QTableWidgetItem(f"{folder}/{name}")
                        name_item.setData(Qt.UserRole, item)
                        name_item.setToolTip(item["path"])  # 悬停显示完整路径
                        time_item = QTableWidgetItem(t)
                        time_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                        self.file_table.setItem(row, 0, name_item)
                        self.file_table.setItem(row, 1, time_item)
                        time_item.setData(Qt.UserRole, item)

            # 设置列宽比例
            try:
                self.text_table.setColumnWidth(1, int(self.text_table.width() * 0.2))
                self.text_table.setColumnWidth(0, int(self.text_table.width() * 0.8))
            except Exception: pass
            try:
                self.image_table.setColumnWidth(1, int(self.image_table.width() * 0.2))
                self.image_table.setColumnWidth(0, int(self.image_table.width() * 0.8))
            except Exception: pass
            try:
                self.file_table.setColumnWidth(1, int(self.file_table.width() * 0.2))
                self.file_table.setColumnWidth(0, int(self.file_table.width() * 0.8))
            except Exception: pass
        except Exception as e:
            QMessageBox.warning(self, "警告", f"更新界面失败: {str(e)}")

    def check_clipboard(self):
        """检查剪贴板内容"""
        try:
            win32clipboard.OpenClipboard()
            if win32clipboard.IsClipboardFormatAvailable(win32clipboard.CF_UNICODETEXT):
                content = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT)
                if content != self.last_clipboard_content:
                    self._handle_text(content)
            elif win32clipboard.IsClipboardFormatAvailable(win32clipboard.CF_HDROP):
                files = win32clipboard.GetClipboardData(win32clipboard.CF_HDROP)
                # 文件去重：计算文件路径列表哈希
                file_hash = hashlib.md5(
                    ("|".join(sorted(files))).encode("utf-8")
                ).hexdigest() if files else None
                if file_hash and file_hash != self.last_file_list_hash:
                    self.last_file_list_hash = file_hash
                    self._handle_files(files)
            elif win32clipboard.IsClipboardFormatAvailable(win32clipboard.CF_DIB):
                image = ImageGrab.grabclipboard()
                if image and isinstance(image, Image.Image):
                    self._handle_image(image)
            win32clipboard.CloseClipboard()
        except Exception as e:
            print(f"Error checking clipboard: {e}")

    def _handle_text(self, text):
        """处理文本内容"""
        if text and text != self.last_clipboard_content:
            self.last_clipboard_content = text
            self.history["text"].append({
                "content": text,
                "timestamp": datetime.now().isoformat()
            })
            self._save_history()
            self._update_ui()

    def _handle_image(self, image):
        """处理图片内容，避免重复保存，确保时间为实际截图时间"""
        try:
            now = datetime.now()
            timestamp_str = now.strftime("%Y%m%d_%H%M%S")
            filename = f"image_{timestamp_str}.png"
            filepath = os.path.join(self.images_dir, filename)
            # 计算图片哈希
            img_bytes = image.tobytes()
            img_hash = hashlib.md5(img_bytes).hexdigest()
            if img_hash == self.last_image_hash:
                return  # 图片内容未变，不保存
            self.last_image_hash = img_hash
            # 确保图片是RGB模式
            if image.mode != 'RGB':
                image = image.convert('RGB')
            image.save(filepath, 'PNG')
            self.history["images"].append({
                "path": filepath,
                "timestamp": now.isoformat()  # 用实际截图时间
            })
            self._save_history()
            self._update_ui()
        except Exception as e:
            QMessageBox.warning(self, "警告", f"保存图片失败: {str(e)}")

    def _handle_files(self, files):
        """处理文件内容，大于设置大小不复制"""
        try:
            for file in files:
                if os.path.exists(file):
                    size = os.path.getsize(file)
                    filename = os.path.basename(file)
                    
                    if size > self.max_file_size:
                        # 只记录，不复制
                        self.history["files"].append({
                            "path": file,
                            "original_path": file,
                            "timestamp": datetime.now().isoformat(),
                            "copied": False
                        })
                        continue
                    
                    # 确保使用当前设置的文件目录
                    new_path = os.path.join(self.files_dir, filename)
                    if os.path.exists(new_path):
                        name, ext = os.path.splitext(filename)
                        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                        new_path = os.path.join(self.files_dir, f"{name}_{timestamp}{ext}")
                    
                    # 复制文件到新目录
                    try:
                        # 确保目标目录存在
                        os.makedirs(os.path.dirname(new_path), exist_ok=True)
                        # 复制文件
                        shutil.copy2(file, new_path)
                        
                        self.history["files"].append({
                            "path": new_path,
                            "original_path": file,
                            "timestamp": datetime.now().isoformat(),
                            "copied": True
                        })
                    except Exception as e:
                        QMessageBox.warning(self, "警告", f"复制文件失败: {str(e)}")
                        continue
            
            self._save_history()
            self._update_ui()
        except Exception as e:
            QMessageBox.warning(self, "警告", f"保存文件失败: {str(e)}")

    def clear_selected(self):
        """清除选中的项目"""
        try:
            current_tab = self.tab_widget.currentIndex()
            if current_tab == 0:  # 文本
                selected_rows = set()
                for index in self.text_table.selectedIndexes():
                    selected_rows.add(index.row())
                # 获取选中行的数据
                items_to_remove = []
                for row in sorted(selected_rows, reverse=True):
                    item = self.text_table.item(row, 0)
                    if item and not item.text().startswith("【"):
                        data = item.data(Qt.UserRole)
                        if data:
                            items_to_remove.append(data)
                # 从历史记录中移除
                for item in items_to_remove:
                    if item in self.history["text"]:
                        self.history["text"].remove(item)
            elif current_tab == 1:  # 图片
                if self.image_view_mode.currentText() == "图片预览":
                    selected_items = self.image_list.selectedItems()
                    for item in selected_items:
                        if not item.text().startswith("【"):
                            data = item.data(Qt.UserRole)
                            if data and data in self.history["images"]:
                                if os.path.exists(data["path"]):
                                    os.remove(data["path"])
                                self.history["images"].remove(data)
                else:
                    selected_rows = set()
                    for index in self.image_table.selectedIndexes():
                        selected_rows.add(index.row())
                    items_to_remove = []
                    for row in sorted(selected_rows, reverse=True):
                        item = self.image_table.item(row, 0)
                        if item and not item.text().startswith("【"):
                            data = item.data(Qt.UserRole)
                            if data:
                                items_to_remove.append(data)
                    for item in items_to_remove:
                        if item in self.history["images"]:
                            if os.path.exists(item["path"]):
                                os.remove(item["path"])
                            self.history["images"].remove(item)
            elif current_tab == 2:  # 文件
                selected_rows = set()
                for index in self.file_table.selectedIndexes():
                    selected_rows.add(index.row())
                items_to_remove = []
                for row in sorted(selected_rows, reverse=True):
                    item = self.file_table.item(row, 0)
                    if item and not item.text().startswith("【"):
                        data = item.data(Qt.UserRole)
                        if data:
                            items_to_remove.append(data)
                for item in items_to_remove:
                    if item in self.history["files"]:
                        if os.path.exists(item["path"]):
                            os.remove(item["path"])
                        self.history["files"].remove(item)
            self._save_history()
            self._update_ui()
        except Exception as e:
            QMessageBox.warning(self, "警告", f"清除选中项目失败: {str(e)}")

    def text_context_menu(self, pos: QPoint):
        index = self.text_table.indexAt(pos)
        row = index.row()
        if row < 0:
            return
        item = self.text_table.item(row, 0)
        if not item or item.text().startswith("【"):
            return
        menu = QMenu(self)
        copy_action = menu.addAction("复制")
        action = menu.exec(self.text_table.viewport().mapToGlobal(pos))
        if action == copy_action:
            data = item.data(Qt.UserRole)
            if data:
                content = data["content"]
            else:
                content = item.text()
            QApplication.clipboard().setText(content)

    def image_context_menu(self, pos: QPoint):
        item = self.image_list.itemAt(pos)
        if not item or item.text().startswith("【"):
            return
        menu = QMenu(self)
        copy_action = menu.addAction("复制图片")
        action = menu.exec(self.image_list.mapToGlobal(pos))
        if action == copy_action:
            data = item.data(Qt.UserRole)
            if data and os.path.exists(data["path"]):
                from PySide6.QtGui import QImage
                img = QImage(data["path"])
                if not img.isNull():
                    QApplication.clipboard().setImage(img)

    def file_context_menu(self, pos: QPoint):
        index = self.file_table.indexAt(pos)
        row = index.row()
        if row < 0:
            return
        item = self.file_table.item(row, 0)
        if not item or item.text().startswith("【"):
            return
        menu = QMenu(self)
        copy_action = menu.addAction("复制路径")
        open_action = menu.addAction("打开所在文件夹")
        action = menu.exec(self.file_table.viewport().mapToGlobal(pos))
        data = item.data(Qt.UserRole)
        if not data:
            return
        
        # 优先使用复制后的路径，如果不存在则使用原始路径
        path = data["path"]
        if not os.path.exists(path) and "original_path" in data:
            path = data["original_path"]
            
        if action == copy_action:
            QApplication.clipboard().setText(path)
        elif action == open_action:
            if os.path.exists(path):
                subprocess.Popen(['explorer', '/select,', path])

    def text_double_clicked(self, item):
        row = item.row()
        # 跳过分组标题行
        if self.text_table.item(row, 0) and self.text_table.item(row, 0).text().startswith("【"):
            return
        content_item = self.text_table.item(row, 0)
        if content_item:
            data = content_item.data(Qt.UserRole)
            if data:
                content = data["content"]
            else:
                content = content_item.text()
            dlg = QDialog(self)
            dlg.setWindowTitle("完整内容")
            vbox = QVBoxLayout(dlg)
            text_edit = QTextEdit()
            text_edit.setReadOnly(True)
            text_edit.setText(content)
            vbox.addWidget(text_edit)
            dlg.setLayout(vbox)
            dlg.resize(500, 300)
            dlg.exec()

    def image_double_clicked(self, item):
        if item.text().startswith("【"): return
        data = item.data(Qt.UserRole)
        if not data or not os.path.exists(data["path"]):
            return
        from PySide6.QtGui import QPixmap
        from PySide6.QtWidgets import QLabel, QDialog, QVBoxLayout
        dlg = QDialog(self)
        dlg.setWindowTitle("图片预览")
        vbox = QVBoxLayout(dlg)
        label = QLabel()
        pix = QPixmap(data["path"])
        label.setPixmap(pix.scaled(600, 600, Qt.KeepAspectRatio, Qt.SmoothTransformation))
        vbox.addWidget(label)
        dlg.setLayout(vbox)
        dlg.exec()

    def file_double_clicked(self, item):
        row = item.row()
        if self.file_table.item(row, 0) and self.file_table.item(row, 0).text().startswith("【"):
            return
        name_item = self.file_table.item(row, 0)
        if name_item:
            data = name_item.data(Qt.UserRole)
            if data:
                # 优先使用复制后的路径，如果不存在则使用原始路径
                path = data["path"]
                if not os.path.exists(path) and "original_path" in data:
                    path = data["original_path"]
                if os.path.exists(path):
                    subprocess.Popen(['explorer', '/select,', path])

    def clear_current_tab(self):
        tab_widget = self.findChild(QTabWidget)
        current_tab = tab_widget.currentIndex()
        reply = QMessageBox.question(self, "确认", "确定要清空当前页所有记录吗？", QMessageBox.Yes | QMessageBox.No)
        if reply != QMessageBox.Yes:
            return
        if current_tab == 0:  # 文本
            self.history["text"].clear()
        elif current_tab == 1:  # 图片
            for item in self.history["images"]:
                path = item["path"]
                if os.path.exists(path):
                    os.remove(path)
            self.history["images"].clear()
        elif current_tab == 2:  # 文件
            for item in self.history["files"]:
                path = item["path"]
                if os.path.exists(path):
                    os.remove(path)
            self.history["files"].clear()
        self._save_history()
        self._update_ui()

    def clear_all_history(self):
        reply = QMessageBox.question(self, "确认", "确定要全部清空所有记录吗？（包括所有文件和图片）", QMessageBox.Yes | QMessageBox.No)
        if reply != QMessageBox.Yes:
            return
        # 删除所有图片
        for item in self.history["images"]:
            path = item["path"]
            if os.path.exists(path):
                os.remove(path)
        # 删除所有文件
        for item in self.history["files"]:
            path = item["path"]
            if os.path.exists(path):
                os.remove(path)
        self.history = {"text": [], "images": [], "files": []}
        self._save_history()
        self._update_ui()

    def clear_old_records(self):
        """清空一个月前的记录"""
        try:
            reply = QMessageBox.question(
                self, 
                "确认", 
                "确定要清空一个月前的所有记录吗？\n（包括文本、图片和文件）", 
                QMessageBox.Yes | QMessageBox.No
            )
            if reply != QMessageBox.Yes:
                return

            # 计算一个月前的日期
            one_month_ago = datetime.now() - timedelta(days=30)
            one_month_ago_str = one_month_ago.isoformat()

            # 记录原始数量
            original_text_count = len(self.history["text"])
            original_image_count = len(self.history["images"])
            original_file_count = len(self.history["files"])

            # 清空文本记录
            self.history["text"] = [
                item for item in self.history["text"]
                if datetime.fromisoformat(item["timestamp"]) > one_month_ago
            ]

            # 清空图片记录
            old_images = []
            new_images = []
            for item in self.history["images"]:
                if datetime.fromisoformat(item["timestamp"]) > one_month_ago:
                    new_images.append(item)
                else:
                    old_images.append(item)
            
            # 删除旧图片文件
            for item in old_images:
                if os.path.exists(item["path"]):
                    try:
                        os.remove(item["path"])
                    except Exception as e:
                        print(f"删除图片失败: {str(e)}")
            
            self.history["images"] = new_images

            # 清空文件记录
            old_files = []
            new_files = []
            for item in self.history["files"]:
                if datetime.fromisoformat(item["timestamp"]) > one_month_ago:
                    new_files.append(item)
                else:
                    old_files.append(item)
            
            # 删除旧文件
            for item in old_files:
                if os.path.exists(item["path"]):
                    try:
                        os.remove(item["path"])
                    except Exception as e:
                        print(f"删除文件失败: {str(e)}")
            
            self.history["files"] = new_files

            # 保存更新后的历史记录
            self._save_history()
            self._update_ui()

            # 计算清理的数量
            cleared_text = original_text_count - len(self.history["text"])
            cleared_images = original_image_count - len(self.history["images"])
            cleared_files = original_file_count - len(self.history["files"])

            # 显示清理结果
            QMessageBox.information(
                self,
                "清理完成",
                f"已清理一个月前的记录：\n"
                f"文本：{cleared_text} 条\n"
                f"图片：{cleared_images} 张\n"
                f"文件：{cleared_files} 个"
            )

        except Exception as e:
            QMessageBox.warning(self, "警告", f"清理旧记录失败: {str(e)}")

    def close_application(self):
        """完全退出应用程序"""
        reply = QMessageBox.question(
            self, 
            "确认退出", 
            "确定要退出程序吗？",
            QMessageBox.Yes | QMessageBox.No
        )
        if reply == QMessageBox.Yes:
            self.tray_icon.hide()
            QApplication.quit()

    def show_about(self):
        """显示关于对话框"""
        dialog = AboutDialog(self)
        dialog.exec()

    def _create_menu_bar(self):
        """创建菜单栏"""
        menubar = self.menuBar()
        
        # 文件菜单
        file_menu = menubar.addMenu("文件")
        
        # 添加退出菜单项
        exit_action = QAction("退出", self)
        exit_action.triggered.connect(self.close_application)
        file_menu.addAction(exit_action)
        
        # 设置菜单
        settings_action = QAction("设置", self)
        settings_action.triggered.connect(self.show_settings)
        menubar.addAction(settings_action)
        
        # 关于菜单
        about_action = QAction("关于", self)
        about_action.triggered.connect(self.show_about)
        menubar.addAction(about_action)

    def show_settings(self):
        """显示设置对话框"""
        dialog = SettingsDialog(self)
        dialog.exec()

def main():
    app = QApplication(sys.argv)
    window = ClipboardManager()
    # 默认隐藏主窗口，只显示托盘图标
    window.hide()
    sys.exit(app.exec())

if __name__ == "__main__":
    main() 